# FIXME: this is all a kluge! REWRITE!
from ..libmoops import deprecated

@deprecated
def format_instruction( asm_code ):
    asm_code = asm_code.split(None, 1)
    if len(asm_code)>1: asm_code=[asm_code[0]]+[x.strip() for x in asm_code[1].replace(',', ' ').split()]
    return asm_code

@deprecated
def splitbits( x ):
    return (int(x[:16], 2), int(x[16:], 2))

@deprecated
def float2int( x ):
    return str(struct.unpack(STRUCT_FORMAT+'I', struct.pack(STRUCT_FORMAT+'f', float(x)))[0])

@deprecated
def int2float( x ):
    return struct.unpack(STRUCT_FORMAT+'f', struct.pack(STRUCT_FORMAT+'I', int(x)))[0]

@deprecated
def decomment( asm_code ):
    return asm_code.replace(';', '#').partition('#')[0].strip()

@deprecated
def pad( string, length ):
    if len(string)<length: string='0'*(length-len(string))+string
    return string[len(string)-length:]

@deprecated
def format_address( target, current=0 ): #current is 0 for jumps
    if target[0] not in '-1234567890':
      target= str(int(jump_table[target])-current) # this will be reconverted to binary
    return format_immediate(target, 18 if current else 28)[:-2] #low 2 bits don't matter, word alignment

@deprecated
def registers( register ): # Converts registers to binary
    #if n < 0: raise ValueError, "must be a positive integer"
    if register[0]!='$': raise TranslationError("Got literal, register expected")
    if register[1].lower()=='f': return fregisters( register )
    if register[1] not in '0123456789' and USE_PSEUDO: reg_num=reg_names.index(register[1:])
    else: reg_num=int(register[1:])
    return pad(bin(reg_num)[2:], 5)

@deprecated
def fregisters( fregister ): # Converts registers to binary
    #if n < 0: raise ValueError, "must be a positive integer"
    if fregister[1].lower()!='f': return registers( fregister )
    return pad(bin(int(fregister[2:]))[2:], 5)

@deprecated
def handle_literal( string ):
    neg=string[0]=='-'
    if neg: string=string[1:]
    if string[0]=='0' and len(string)>1:
        if string[1]=='x': ret= int(string, 16)
        elif string[1]=='b': ret= string
        else: ret=int(string, 8)
    else: ret= int(string)
    return bin((1<<32)-ret if neg else ret)[2:] # cut off the 0b prefix, and two's complement negatives

@deprecated
def format_immediate( target , length=16 ):
    if target[0] not in '-1234567890':
        target= str(jump_table[target])
    return pad(handle_literal(target), length)

@deprecated
def depseudo( asm_code ):
    op=format_instruction( asm_code )
    if op[0]=='nop': return ("sll $zero,$zero,0",)

    if op[0] in ('div', 'divu', 'mul', 'mulu') and len(op)==4:
        if op[3][0]!='$':
            tmp=(depseudo("li $at,%s"%op[3]))
            op[3]='$at'
        else: tmp=
        if op[0]=='mul': op[0]='mult'
        if op[0]=='mulu': op[0]='multu'
        return tmp+("%s %s,%s"%(op[0], op[2], op[3]), "mflo %s"%op[1])

    if op[0] in ('rem', 'remu'):
        if op[3][0]!='$':
            tmp=(depseudo("li $at,%s"%op[3]))
            op[3]='$at'
        else: tmp=()
        op[0]='divu' if op[0][-1]=='u' else 'div'
        return tmp+("%s %s,%s"%(op[0], op[2], op[3]), "mflo %s"%op[1])

    if op[0] in ('add', 'addu', 'sub', 'subu') and op[3][0]!='$':
        if op[0] in ('sub', 'subu'):
            if op[3][0]=='-': op[3]=op[3][1:]
            else: op[3]='-'+op[3]
            op[0]='add' if op[0]=='sub' else 'addu'
        if op[0][-1]=='u': op[0]=op[0][:-1]+'iu '
        else: op[0]+='i '

        return (op[0]+', '.join(op[1:]),)

    if op[0] in ('beq', 'bne') and op[2][0]!='$':
        hi, lo=splitbits(format_immediate(op[2], 32))
        if hi: return ("lui $at,%s"%hi, "ori $at,$zero,%s"%lo, "%s %s, $at, %s"%(op[0], op[1], op[3]))
        return ("ori $at,$zero,%s"%lo, "%s %s, $at, %s"%(op[0], op[1], op[3]))

    if op[0] in ('blt', 'bge'):
        set_="slt%s $at,%s,%s"%('i' if op[2][0]!='$' else '', op[1], op[2])
        branch="%s $at,$zero,%s"%('bne' if op[0]=='blt' else 'beq', op[3])
        return (set_, branch)

    if op[0] in ('bgt', 'ble'):
        set_="slt%s $at,%s,%s"%('i' if op[2][0]!='$' else '', op[2], op[1])
        branch="%s $at,$zero,%s"%('bne' if op[0]=='bgt' else 'beq', op[3])
        return (set_, branch)

    if op[0] in ('mov', 'move'): return ("addu %s,$zero,%s"%(op[1], op[2]),)

    if op[0]=='not': return ("nor %s,%s,$zero"%(op[1], op[2]),)

    if op[0]=='la':
      if op[2][0] not in '-0123456789': hi=lo=op[2]
      else: hi, lo=splitbits(format_immediate(op[2], 32))
      if hi: return ("lui %s,%s"%(op[1], hi), "ori %s,%s,%s"%(op[1], op[1], lo))
      return ("ori %s,$zero,%s"%(op[1], lo),)

    if op[0]=='li.s':
        hi, lo=splitbits(format_immediate(float2int(op[2]), 32))
        if hi: return ("lui $at,%s"%hi, "ori $at,$at,%s"%lo, "mtc1 $at,%s"%op[1])
        return ("ori $at,$zero,%s"%(lo), "mtc1 $at,%s"%op[1])

    if op[0]=='li':
        hi, lo=splitbits(format_immediate(op[2], 32))
        if hi: return ("lui %s,%s"%(op[1], hi), "ori %s,%s,%s"%(op[1], op[1], lo))
        return ("ori %s,$zero,%s"%(op[1], lo),)

    if op[0] in ('lw', 'lwc1') and len(op)==3 and '(' not in op[2]:
        if op[2][0] not in '-0123456789': hi=lo=op[2]
        else: hi, lo=splitbits(format_immediate(op[2], 32))
        if hi: return ("lui $at,%s"%hi, "ori $at,$at,%s"%lo, "%s %s,0($at)"%(op[0], op[1]))
        return ("ori $at,$zero,%s"%lo, "%s %s,0($at)"%(op[0], op[1]))

    if op[0]=='mul':
        if len(op)==3:
            return ("mult %s, %s"%(op[1], op[2]),)
        return ("mult %s, %s"%(op[2], op[3]), "mflo %s"%op[1])

    if op[0]=='b': return ("bgez $zero,%s"%op[1],)

    return (asm_code,)